#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#define ip "172.19.66.170"
#define port 8080
int main()
{
    int sock =  socket(AF_INET,SOCK_STREAM,0);//SOCK_STREAM 表示套接字的类型为流式套接字，它提供了可靠的、面向连接的、基于字节流的通信，通常用于 TCP 协议
    if(sock < 0)
    {
        perror("socket");
        return -1;
    }
    
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = inet_addr(ip);
    if(bind(sock,(struct slockaddr*)&addr,sizeof(addr)) < 0) //bind 函数用于将一个套接字与特定的地址（IP 地址和端口号）关联起来
    {
        perror("bind");
        return -1;
    }
    
    //设置地址复用
    int on = 1;
    if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) < 0) //设置套接字选项，允许地址重用
    {
        perror("setsockopt");
        return -1;
    }

    //监听端口：最大等待队列
    if(listen(sock,10) < 0)
    {
        perror("listen");
    }

    //accept函数是阻塞的，当有客户端接入时才返回新客户端套接字
    //客户端连接套接字
    
    printf("等待客户端连接...\n");
    struct sockaddr_in clientAddr;
    socklen_t len = sizeof(clientAddr);
    int clientSock = accept(sock,(struct sockaddr*)&clientAddr,&len); //使用 accept 函数接收传入的连接请求，创建一个新的套接字，并将其赋值给 clientSock
    if(clientSock < 0)
    {
        perror("accept");
        return -1;
    }

    printf("接收到客户端的连接，套接字是：%d\n",clientSock);
    
    while(1)
    {
        char msg[100] = {0};
       if(recv(clientSock,msg,100,0) <= 0 ) //使用 recv 函数从客户端套接字 clientSock 中接收数据，并将其存储在名为 msg 的缓冲区中
       {
           perror("客户端已下线");
           return -1;
        
       }
        printf("收到来自客户端的消息：%s\n",msg);
     
    }
   
   
    close(clientSock);
    close(sock);
    return 0;
}